#pragma once
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <sys/wait.h>

//最大容量
#define MAX 6
#define max_size 1024
//随机数范围
constexpr int min_t=1;
constexpr int max_t=100;

struct Data
{
    Data(in_port_t port,struct in_addr addr,int fd,const char* ptr)
    :_port(port),_addr(addr),_fd(fd),_ptr(ptr)
    {}

    Data()=default;

    //客户端地址
    struct in_addr _addr;
    //客户端端口
    in_port_t _port;
    //客户端文件描述符
    int _fd;
    //任务
    const char* _ptr;
};

template<class T>
class cycle_p_c
{
public:
    cycle_p_c()
    {
        //缓存空间
        _buffer.resize(MAX);
        //锁
        pthread_mutex_init(&p_mutex,NULL);
        pthread_mutex_init(&c_mutex,NULL);
        pthread_mutex_init(&tasks,NULL);
        //信号量
        sem_init(&p_message,0,MAX);
        sem_init(&c_message,0,0);
        //下标
        tail=0;
        head=0;
    }
    ~cycle_p_c()
    {
        pthread_mutex_destroy(&p_mutex);
        pthread_mutex_destroy(&c_mutex);
        pthread_mutex_destroy(&tasks);
        sem_destroy(&p_message);
        sem_destroy(&c_message);
    }

    //生产
    void push_back(const T& data)
    {
        //看信号量是否足够(生产信号量-1)
        sem_wait(&p_message);
        //此时说明已经申请到信号量
        pthread_mutex_lock(&p_mutex);
        
        // pthread_mutex_lock(&tasks);
        // std::cout<<"我创建任务了哦..."<<std::endl;
        // pthread_mutex_unlock(&tasks);

        //生产
        head%=MAX;
        _buffer[head++]=data;
        //消费信号量+1
        sem_post(&c_message);

        std::cout<<"push"<<std::endl;
        
        pthread_mutex_unlock(&p_mutex);
    }
    //消费
    T pop()
    {
        //看信号量是否足够(消费信号量-1)
        sem_wait(&c_message);
        //此时说明已经申请到信号量
        pthread_mutex_lock(&c_mutex);
        
        //消费
        struct Data data=_buffer[tail++];
        tail%=MAX;
        //生产信号量+1
        sem_post(&p_message);
        std::cout<<"pop"<<std::endl;
        pthread_mutex_unlock(&c_mutex);
        return data;
    }
    //处理任务
    void Handle_tasks(struct Data* ptr)
    {
        pthread_mutex_lock(&tasks);

        std::cout<<"已经收到:"<<"客户端:"<<inet_ntoa(ptr->_addr)<<" 端口:"<<ptr->_port<<"的任务"<<std::endl;

        pthread_mutex_unlock(&tasks);

        char buffer[max_size]={0};
        //发送给客户端
        snprintf(buffer, sizeof(buffer)-1,"客户端：%s_%d已经执行完毕……",inet_ntoa(ptr->_addr),ntohs(ptr->_port));
        ssize_t sz = send(ptr->_fd,buffer,sizeof(buffer)-1,0);
        close(ptr->_fd);
    }
private:
    //数据缓存
    std::vector<T> _buffer;
    //信号变量*3
    sem_t p_message;
    sem_t c_message;
    //两个下标
    size_t head;
    size_t tail;
    //两个互斥锁(确保每次只有一个生产和一个消费并发执行)
    pthread_mutex_t p_mutex;
    pthread_mutex_t c_mutex;
    //任务拿取锁
    pthread_mutex_t tasks;
};